#if !defined(AFX_AESENCREGKEY_H__ADDAA2B4_77EB_4E8D_9F60_676CA6BE2897__INCLUDED_)
#define AFX_AESENCREGKEY_H__ADDAA2B4_77EB_4E8D_9F60_676CA6BE2897__INCLUDED_

#if _MSC_VER > 1000
#  pragma once
#endif // _MSC_VER > 1000

//
// AESEncRegKey.h : header file
//

//
// AES helper structures
#include "AESHelper.h"

//
// Crypto++ Includes
#pragma warning(push)
#pragma warning(disable:4231)
#include "modes.h"
#include "aes.h"
#include "filters.h"
#pragma warning(pop)

/////////////////////////////////////////////////////////////////////////////
// CAESEncRegKey

class CAESEncRegKey {

// Construction/Destruction
public:
    CAESEncRegKey( );
    CAESEncRegKey( HKEY hKey, LPCTSTR pszSubKey, LPCTSTR pszValueName );
    CAESEncRegKey( const BYTE* cbKey, UINT nKeyLength,
                   const BYTE* cbIV,  UINT nIVLength );

    virtual ~CAESEncRegKey();

// Implementation
public:

    LONG ReadDWORD ( DWORD& dwValue, BOOL bEncrypted = FALSE ) const;
    LONG ReadString( CString& szValue, BOOL bEncrypted = FALSE ) const;
	  LONG ReadString( LPTSTR pszValue, DWORD* dwCharCount,
                     BOOL bEncrypted = FALSE ) const;
    LONG ReadBinary( BYTE* pcbData, DWORD* dwSize,
                     BOOL bEncrypted = FALSE ) const;

    LONG WriteDWORD( DWORD dwValue, BOOL bEncrypt = FALSE ) const;
    LONG WriteString( LPCTSTR pszData, BOOL bEncrypt = FALSE ) const;
    LONG WriteBinary( const BYTE* pcbData, UINT nSize,
                      BOOL bEncrypt = FALSE ) const;


    const CString& GetValueName( ) const;
    const CString& GetSubKey( ) const;

    const BYTE* GetIV( ) const;
    const BYTE* GetKey( ) const;

    UINT GetKeyLength( ) const;
    UINT GetIVLength( ) const;    


    BOOL SetValueName( LPCTSTR pszValueName );
    BOOL SetSubKey( LPCTSTR pszSubKey );

    BOOL SetKey( const BYTE* cbKey, UINT nLength );
    BOOL SetIV( const BYTE* cbIV, UINT nLength );

    BOOL SetHKEY( HKEY hKey );

protected:

    LONG WriteEncString( LPCTSTR pszData ) const;
    LONG WriteNonEncString( LPCTSTR pszData ) const;

    LONG WriteEncDWORD( DWORD dwData ) const;
    LONG WriteNonEncDWORD( DWORD dwData ) const;

    LONG WriteEncBinary( const BYTE *pcbData, UINT nSize ) const;
    LONG WriteNonEncBinary( const BYTE *pcbData, UINT nSize ) const;

    LONG ReadEncString( CString &szValue ) const;
    LONG ReadNonEncString( CString &szValue ) const;

    LONG ReadEncDWORD( DWORD& dwValue ) const;
    LONG ReadNonEncDWORD( DWORD& dwValue ) const;

    LONG ReadEncBinary( BYTE* pcbData, DWORD* dwSize ) const;
    LONG ReadNonEncBinary( BYTE* pcbData, DWORD* dwSize ) const;

	LONG WriteData( const BYTE *pcbData, UINT nSize, DWORD dwType = REG_BINARY) const;    
    LONG ReadData( BYTE** pcbData, DWORD* dwSize ) const;

    LONG DecryptData( const BYTE* pcbEncryptedData, DWORD dwEncryptedSize,
                      BYTE** pcbDecryptedData, DWORD* pdwDecryptedSize ) const;
    LONG EncryptData( const BYTE* pcbPlaintext, DWORD dwPlaintextSize,
                      BYTE **pcbEncryptedData, DWORD *pdwEncryptedSize) const;


protected:

    AESIV   _EncIV;
    
    AESKey  _EncKey;

    HKEY    _hKey;

    CString _szSubKey;
    CString _szValueName;

private:

    //
    // Make Copy, Operator=(), Operator==(), and Operator!=()
    //   Private so they cannot be invoked
    //
    // These can be made Public if desired
    CAESEncRegKey( const CAESEncRegKey& rhs ) { *this = rhs; }

    CAESEncRegKey& operator=( const CAESEncRegKey& rhs ) {
        
        if( this == &rhs ) { return *this; }

        _EncIV  = rhs._EncIV;
        _EncKey = rhs._EncKey;
        _hKey   = rhs._hKey;

        _szSubKey    = rhs._szSubKey;
        _szValueName = rhs._szValueName;

        return *this;
    }

    BOOL operator==( const CAESEncRegKey& rhs ) {
        
        if( this == &rhs ) { return TRUE; }

        BOOL bResult = TRUE;

        bResult |= _EncIV  == rhs._EncIV  ? TRUE : FALSE;
        bResult |= _EncKey == rhs._EncKey ? TRUE : FALSE;
        bResult |= _hKey   == rhs._hKey   ? TRUE : FALSE;

        if( FALSE == bResult ) { return bResult; }

        bResult |= _szSubKey    == rhs._szSubKey    ? TRUE : FALSE;
        bResult |= _szValueName == rhs._szValueName ? TRUE : FALSE;

        return bResult;
    }

    BOOL operator!=( const CAESEncRegKey& rhs ) { return !( operator==( rhs ) ); }
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_AESENCREGKEY_H__ADDAA2B4_77EB_4E8D_9F60_676CA6BE2897__INCLUDED_)
